package com.donar.concurrent.lock;

import java.util.Random;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Created by donar on 18/2/28.
 */
public class Semaphore {

    Sync sync;
    public Semaphore(int permits){
        sync = new Sync(permits);
    }
    static class Sync extends AbstractQueuedSynchronizer{
        public Sync(int permit){
            setState(permit);
        }

        @Override
        protected boolean tryAcquire(int arg) {
            for (;;){
                int available = getState();
                int rest = available - arg;
                if(rest<0)return false;
                if(compareAndSetState(available,rest)) return true;
            }
        }

        @Override
        protected boolean tryRelease(int arg) {
            for (;;){
                int available = getState();
                int rest = available+arg;
                if(compareAndSetState(available,rest)) return true;
            }
        }


    }


    public boolean acquire(){
        return sync.tryAcquire(1);
    }
    public void release(){
        sync.release(1);
    }

    public static void main(String[] args) {
        Runnable runnable = new Runnable() {
            ReentrantLock lock = new ReentrantLock();

            @Override
            public void run() {
                lock.lock();
                try {
                    Thread.sleep(1000000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                lock.unlock();
            }
        };
        for (int i = 0; i < 3; i++) {
            new Thread(runnable,"Consumer"+i).start();

        }

    }
}

